use reqwest::Client;
use serde::{Deserialize, Serialize};

use crate::common::Response;

#[derive(Clone, Debug, Serialize)]
pub struct PaidUnionIdReq {
    openid: String,
    transaction_id: Option<String>,
    mch_id: Option<String>,
    out_trade_no: Option<String>,
}

impl PaidUnionIdReq {
    pub fn new<T>(openid: T) -> Self
    where
        T: AsRef<str>,
    {
        Self {
            openid: openid.as_ref().to_owned(),
            transaction_id: None,
            mch_id: None,
            out_trade_no: None,
        }
    }

    pub fn more<T>(
        openid: T,
        transaction_id: Option<T>,
        mch_id: Option<T>,
        out_trade_no: Option<T>,
    ) -> Self
    where
        T: AsRef<str>,
    {
        Self {
            openid: openid.as_ref().to_owned(),
            transaction_id: transaction_id.map(|v| v.as_ref().to_owned()),
            mch_id: mch_id.map(|v| v.as_ref().to_owned()),
            out_trade_no: out_trade_no.map(|v| v.as_ref().to_owned()),
        }
    }
}

#[derive(Clone, Debug, Deserialize)]
pub struct PaidUnionIdRes {
    pub unionid: String,
}

type Res = Response<PaidUnionIdRes>;

pub async fn paid_union_id<T>(token: T, params: &PaidUnionIdReq) -> Result<Res, reqwest::Error>
where
    T: AsRef<str>,
{
    let url = format!(
        "https://api.weixin.qq.com/wxa/getpaidunionid?access_token={}",
        token.as_ref()
    );
    let client = Client::new();
    client
        .get(url)
        .json(params)
        .send()
        .await?
        .json::<Res>()
        .await
}
